package com.mobilesales.android.activities.tasks;

import java.util.ArrayList;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import android.widget.SlidingDrawer;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.GoogleMap.OnInfoWindowClickListener;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.maps.GeoPoint;
import com.mobilesales.android.R;
import com.mobilesales.android.activities.IRefreshable;
import com.mobilesales.android.adapters.SlidingMenus;
import com.mobilesales.android.adapters.TaskAdapter;
import com.mobilesales.android.c2dm.C2DMMessaging;
import com.mobilesales.android.c2dm.NotificationReceiver;
import com.mobilesales.android.database.ClientManager;
import com.mobilesales.android.database.TaskManager;
import com.mobilesales.android.infrastructure.IPushpinSelected;
import com.mobilesales.android.infrastructure.MapOverlays;
import com.mobilesales.android.model.clients.Client;
import com.mobilesales.android.model.tasks.CyclicTask;
import com.mobilesales.android.model.tasks.Schedule;
import com.mobilesales.android.model.tasks.Task;
import com.mobilesales.android.util.Constants;
import com.mobilesales.android.util.DateUtil;
import com.mobilesales.android.util.Geolocalization;
import com.mobilesales.android.util.MessageBox;
import com.mobilesales.android.util.SelectDateTime;
import com.mobilesales.android.util.Settings;

public class TaskMaps extends FragmentActivity implements IPushpinSelected,
		IRefreshable {

	private MapOverlays itemizedOverlay = null;
	// private MapController mapController;
	private static final int INITIAL_ZOOM = 12;

	// private static final int CONTEXT_CENTER = 0;
	// private static final int CONTEXT_SHOWHIDE = 1;
	// private static final int CONTEXT_DETAILS = 2;

	private Date selectedDate;
	private List<Task> tasksOfDay;
	private Map<Task, LatLng> taskGeopointMap;

	private TaskAdapter itemsAdapter;
	private ListView taskList;
	private SlidingDrawer slidingDrawer;

	private NotificationReceiver receiver;
	private Handler handler = new Handler();
	private GoogleMap mapview;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.task_maps);
		new SlidingMenus(this);
		this.initTaskList();
		this.initMap();
		receiver = new NotificationReceiver() {
			@Override
			public void onMessage(String msg) {
				refresh();
			}
		};
		C2DMMessaging.addNotificationReceiver(receiver);

		Bundle bundle = this.getIntent().getExtras();
		if (bundle != null && bundle.containsKey(Constants.SelectedDate)) {
			selectedDate = (Date) bundle.get(Constants.SelectedDate);
			Log.i("selectedDate", selectedDate.toLocaleString());
			loadItems();

		} else {
			MessageBox.show(this, getString(R.string.ErrorTaskList));
			finish();
		}
	}

	/**
	 * Khoi tao ban do.
	 */
	private void initMap() {
		mapview = ((SupportMapFragment) getSupportFragmentManager()
				.findFragmentById(R.id.mapView)).getMap();
		mapview.moveCamera(CameraUpdateFactory.zoomTo(INITIAL_ZOOM));
		mapview.setMyLocationEnabled(false);
		mapview.setOnInfoWindowClickListener(new OnInfoWindowClickListener() {

			public void onInfoWindowClick(Marker arg0) {
				// TODO Auto-generated method stub
				openOptionsMenu();
			}
		});
	}

	private void loadItems() {
		tasksOfDay = this.getItems();
		if (tasksOfDay != null) {
			this.setItemsSource(tasksOfDay);
		} else {
			MessageBox.show(this, getString(R.string.ErrorTaskList));
			finish();
		}
	}

	protected void setItemsSource(List<Task> source) {
		List<Task> itemsToDisable = new ArrayList<Task>();
		taskGeopointMap = new HashMap<Task, LatLng>();
		boolean success = true;
		for (int i = 0; i < source.size(); i++) {
			boolean disableItem = false;
			Task tsk = source.get(i);

			if (tsk.ClientId != null && tsk.ClientId != 0) {
				Client clnt = this.getClient(tsk.ClientId);
				if (clnt != null) {
					String address = clnt.Street + ", " + clnt.City;
					String desc = clnt.Name + "\n" + clnt.Street + "\n"
							+ clnt.Zipcode + " " + clnt.City;

					LatLng lc = convertAddress(address);

					taskGeopointMap.put(tsk, lc);
					if (!lc.equals(new LatLng(0.0, 0.0)))
						this.addPushpin(lc, desc);

				} else {
					disableItem = true;
					MessageBox.show(this, getString(R.string.ErrorClient));
				}
			} else {
				disableItem = true;
			}

			if (disableItem) {
				itemsToDisable.add(tsk);
			}
			success &= !disableItem;
		}

		itemsAdapter = new TaskAdapter(this, R.layout.task_list_item, source,
				itemsToDisable);
		taskList.setAdapter(itemsAdapter);

		if (!success) {
			MessageBox.show(this, getString(R.string.ErrorTaskOnMap));
			this.slidingDrawer.animateOpen();
		}
	}

	public LatLng convertAddress(String address) {
		try {
			Geocoder geoCoder = new Geocoder(this);
			List<Address> addressList = geoCoder.getFromLocationName(address,
					10);
			if (addressList != null && addressList.size() > 0) {
				double lat = addressList.get(0).getLatitude();
				double lng = addressList.get(0).getLongitude();
				return new LatLng(lat, lng);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} // end catch
		return new LatLng(0, 0);
	}

	/**
	 * Lay vi tri hien tai cua nguoi dung
	 */
	private void initCurrentPosition() {
		if (this.itemizedOverlay != null) {
			try {
				Location lc = Geolocalization.getCurrentLocation(this);
				if (lc != null) {
					LatLng loc = new LatLng(lc.getLatitude(), lc.getLongitude());
					this.itemizedOverlay.setCurrentLocation(loc);
				} else {
					MessageBox.show(this,
							getString(R.string.ErrorGeolocalization));
				}
			} catch (Exception ex) {
				// showErrorGPS();
				Log.i("getLocation", getString(R.string.ErrorGeolocalization));
			}
		}
	}

	// private void showErrorGPS() {
	// AlertDialog.Builder alertDialog = new AlertDialog.Builder(this);
	//
	// // Setting Dialog Title
	// alertDialog.setTitle("GPS is settings");
	//
	// // Setting Dialog Message
	// alertDialog
	// .setMessage("GPS is not enabled. Do you want to go to settings menu?");
	//
	// // Setting Icon to Dialog
	// // alertDialog.setIcon(R.drawable.delete);
	// // On pressing Settings button
	// alertDialog.setPositiveButton("Settings",
	// new DialogInterface.OnClickListener() {
	// public void onClick(DialogInterface dialog, int which) {
	// Intent intent = new Intent(
	// android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
	// startActivity(intent);
	// }
	// });
	//
	// // on pressing cancel button
	// alertDialog.setNegativeButton("Cancel",
	// new DialogInterface.OnClickListener() {
	// public void onClick(DialogInterface dialog, int which) {
	// dialog.cancel();
	// }
	// });
	// // Showing Alert Message
	// alertDialog.show();
	// }

	/**
	 * 
	 * @param tsk
	 */
	private void showDetails(Task tsk) {
		boolean isCyclicTask = (tsk instanceof CyclicTask);
		Intent intent = new Intent(this, DetailsTask.class);
		intent.putExtra(Constants.TaskId, tsk.Id);
		intent.putExtra(Constants.IsCyclicTask, isCyclicTask);
		this.startActivityForResult(intent, 0);
	}

	private void initTaskList() {
		slidingDrawer = (SlidingDrawer) this.findViewById(R.id.slidingDrawer);
		taskList = (ListView) this.findViewById(R.id.taskList);
		taskList.setEmptyView(this.findViewById(R.id.taskListEmpty));
		taskList.setOnItemClickListener(new OnItemClickListener() {

			public void onItemClick(AdapterView<?> adpt, View view,
					int position, long id) {
				if (itemsAdapter != null) {
					Task tsk = itemsAdapter.getItem(position);
					showDetails(tsk);
				}
			}
		});
		this.registerForContextMenu(taskList);
	}

	private Client getClient(int clientId) {
		ClientManager manager = new ClientManager(this);
		Client result = manager.GetClient(clientId);
		manager.Close();
		return result;
	}

	protected List<Task> getItems() {
		if (this.selectedDate != null) {
			List<Task> tasks = getTasks(selectedDate);
			List<CyclicTask> cyclicTasks = getCyclicTasks(selectedDate);
			List<Task> tasksOfDay = new ArrayList<Task>();
			if (tasks != null && cyclicTasks != null) {
				for (Task tsk : tasks)
					tasksOfDay.add(tsk);
				for (CyclicTask tsk : cyclicTasks)
					tasksOfDay.add(tsk);
				return tasksOfDay;
			}
		}
		return null;
	}

	private List<CyclicTask> getCyclicTasks(Date currentDate) {
		Log.i("currentDate", currentDate.toLocaleString());
		TaskManager manager = new TaskManager(this);
		List<CyclicTask> tasks = manager.GetCyclicTaskList(Settings
				.getSettings().getEmployeeId());
		manager.Close();

		List<CyclicTask> taskInTime = null;
		if (tasks != null) {
			taskInTime = new ArrayList<CyclicTask>();
			GregorianCalendar calendar = new GregorianCalendar();
			for (CyclicTask tsk : tasks) {
				Date date = DateUtil.parseDate(tsk.StartTime);
				calendar.setTime(date);
				GregorianCalendar current = new GregorianCalendar();
				current.setTime(currentDate);
				current.set(GregorianCalendar.HOUR_OF_DAY,
						calendar.get(GregorianCalendar.HOUR_OF_DAY));
				current.set(GregorianCalendar.MINUTE,
						calendar.get(GregorianCalendar.MINUTE));

				Log.i("Current", current.getTime().toLocaleString());
				Log.i("Day", calendar.getTime().toLocaleString());

				long diff = Math.abs(current.getTimeInMillis()
						- calendar.getTimeInMillis())
						/ (24 * 60 * 60 * 1000);

				Log.i("diff", diff + "");
				Log.i("taskInterval", tsk.TaskInterval + "");
				Log.i("diff % tsk.TaskInterval", (diff % tsk.TaskInterval) + "");

				if (diff % tsk.TaskInterval == 0)
					taskInTime.add(tsk);
			}
			Log.i("MobileSales", "taskInTime:" + taskInTime.size());

		}
		return taskInTime;
	}

	private List<Task> getTasks(Date date) {
		List<Task> tasks = null;
		TaskManager manager = new TaskManager(this);
		List<Schedule> schedules = manager.GetScheduleList(Settings
				.getSettings().getEmployeeId());
		if (schedules != null) {
			tasks = new ArrayList<Task>();
			for (Schedule s : schedules) {
				List<Task> stasks = manager.GetTaskList(s.Id);
				if (stasks != null) {
					tasks.addAll(stasks);
				} else {
					tasks = null;
					break;
				}
			}
		}
		manager.Close();
		SelectDateTime selectDate = new SelectDateTime(this);
		if (tasks != null) {
			List<Task> incorrect = new ArrayList<Task>();
			for (Task t : tasks) {
				String currentDate = selectDate.FormatDate(date);
				String taskDate = selectDate.FormatDate(t.StartTime);
				if (!currentDate.equals(taskDate)) {
					incorrect.add(t);
				}
			}
			for (Task t : incorrect)
				tasks.remove(t);
		}
		return tasks;
	}

	protected boolean isRouteDisplayed() {
		return false;
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();
		if (receiver != null)
			C2DMMessaging.removeNotificationReceiver(receiver);
	}

	public void refresh() {
		handler.post(new Runnable() {
			public void run() {
				finish();
			}
		});
	}

	/*
	 * public void addPushpin(String address, String description) { Location loc
	 * = new Location(address); // Location loc =
	 * Geolocalization.reverseGeocode(this, address); if (loc != null) {
	 * GeoPoint gp = new GeoPoint((int) (loc.getLatitude() * 1E6), (int)
	 * (loc.getLongitude() * 1E6)); this.addPushpin(gp, description); } }
	 */

	//
	public void addPushpin(LatLng latlng, String description) {

		if (itemizedOverlay == null) {
			itemizedOverlay = new MapOverlays(this);
			itemizedOverlay.setMaps(mapview);
			initCurrentPosition();
			// List<Overlay> mapOverlays = new ArrayList<Overlay>();

			// itemizedOverlay = new MapOverlays(drawable, this);
			// itemizedOverlay.setMap(mapview);
			// itemizedOverlay.setPushpinSelectedListener(this);

			// this.initCurrentPosition();
			// mapOverlays.add(itemizedOverlay);
		}

		Log.i("addPushpin", latlng.latitude + "," + latlng.longitude);
		itemizedOverlay.addItem(latlng, description);
		// OverlayItem overtask = new OverlayItem(gp, description, description);
		// itemizedOverlay.addOverlay(overtask);
		// mapController.animateTo(gp);
	}

	private Task getTaskFromGeopoint(LatLng gp) {
		if (taskGeopointMap != null) {
			for (Task tsk : taskGeopointMap.keySet()) {
				if (taskGeopointMap.get(tsk).equals(gp)) {
					return tsk;
				}
			}
		}
		return null;
	}

	public void OnPushpinSelected(GeoPoint gp) {
		/*
		 * Task tsk = this.getTaskFromGeopoint(gp); if (tsk != null &&
		 * itemsAdapter != null) { this.itemsAdapter.setActiveTask(tsk); }
		 */

	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {

		if (itemizedOverlay != null) {
			Marker item = itemizedOverlay.getCurrentItem();
			if (item != null
					&& !item.equals(itemizedOverlay.getCurrentLocationItem())) {
				MenuInflater inflater = getMenuInflater();
				inflater.inflate(R.menu.map_menu, menu);

				Location loc = Geolocalization.getCurrentLocation(this);
				if (loc == null) {
					menu.getItem(2).setEnabled(false);
				}
				// TODO:remove below
				menu.removeItem(R.id.route);
				return true;
			}
		}
		if (Build.VERSION.SDK_INT < 11)
			supportInvalidateOptionsMenu();
		else
			invalidateOptionsMenu();
		return super.onCreateOptionsMenu(menu);
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.route:
			break;
		case R.id.hidee:
			if (itemizedOverlay != null) {
				Marker oItem = itemizedOverlay.getCurrentItem();
				boolean isVisible = !itemizedOverlay.getVisibility(oItem);
				if (oItem != null) {
					itemizedOverlay.setVisibility(oItem, isVisible);
					Task tsk = this.getTaskFromGeopoint(oItem.getPosition());
					itemsAdapter.setTaskVisibility(tsk, isVisible);
				}
			}
			break;
		case R.id.details:
			if (itemizedOverlay != null) {
				Marker oItem = itemizedOverlay.getCurrentItem();
				if (oItem != null) {
					Task tsk = this.getTaskFromGeopoint(oItem.getPosition());
					this.showDetails(tsk);
				}
			}
			break;
		}
		if (Build.VERSION.SDK_INT < 11)
			supportInvalidateOptionsMenu();
		else
			invalidateOptionsMenu();
		return true;
	}
}
